/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */
 
#include "Types.h"
#include "TypeMap.h"
#include "ReferenceTypeMap.h"
#include "DynamicTypeMap.h"


static struct type_map_vtable dynamicMapVtable =
{
	&_type_map_map,
	&_dynamic_map_get_id,
	&_type_map_get_name,
	&_type_map_get_reader,
	&_type_map_get_writer,
	&_type_map_get_structure,
	&_type_map_get_library_id,
	&_dynamic_map_get_mapped_id,
	&_type_map_is_valid_id,
	&_type_map_is_valid_name,
	&_type_map_get_size
};

void dynamic_type_map_init( dynamic_type_map * map, type_library * library, type_map * reference )
{
	reference_type_map_init( &map->ref_map, library, reference );
	map->ref_map.map.__vt = &dynamicMapVtable;
	map->last_map_id = 1;
}

void dynamic_type_map_init_reflect( dynamic_type_map * map, type_library * library )
{
	reference_type_map_init( &map->ref_map, library, NULL );
	reference_type_map_set_reference( &map->ref_map, (type_map *) map );
	map->ref_map.map.__vt = &dynamicMapVtable;
	map->last_map_id = 1;
}

static int get_next_id( dynamic_type_map * map )
{
	int id;
	int rc;
		
	while ( true )
	{
		id = map->last_map_id;
		map->last_map_id++;
		
		// check if the id hasn't been manually mapped earlier.
		// if returns error, then we can map to this id.
		rc = type_map_get_library_id( (type_map*) map, id );
		if ( rc <= NOTYPE ) break;
		
		
	}
	
	return id;
}

int _dynamic_map_get_id( type_map * map, type_name * name )
{
	int systemid;
	int rc;
	// If already mapped, return the value.
	// call the super function, not the normal one.
	int id = _type_map_get_id( map, name );
	if ( id > NOTYPE ) return id;
	
	id = get_next_id( (dynamic_type_map*)map );
	
	systemid = type_library_get_id( type_map_get_library( map ), name );
	if ( systemid <= NOTYPE ) return systemid;
	
	rc = type_map_map( map, id, systemid );
	if ( rc == TYPE_OK ) return id;
	return rc;
}

int _dynamic_map_get_mapped_id( type_map * map, int systemId )
{
	int rc;
	int id = _type_map_get_mapped_id( map, systemId );
	if ( id >= NOTYPE ) return id;
	
	id = get_next_id( (dynamic_type_map*) map );
	rc = type_map_map( map, id, systemId );
	if ( rc == TYPE_OK ) return id;
	return rc;
}
